package com.netrain.ehp.gateway.route;

import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.AbstractListener;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.netrain.ehp.gateway.constant.GatewayConstant;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.annotation.Configuration;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.Yaml;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.concurrent.Executor;

/**
 * 网关路由配置动态更新、发布
 *
 * @author gaoliangliang
 * @date 2022/2/15
 * @since 1.0.0
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
public class GatewayRouteHandler {

    private final RouteDefinitionWriter routeDefinitionWriter;
    private final ConfigService configService;
    @Value("${service_prefix}")
    private String service_prefix;
    @Value("${namespace}")
    private String namespace;

    @PostConstruct
    private void initRoute() {
        try {
            String routeConfig = configService.getConfig(GatewayConstant.DATA_ID, GatewayConstant.GROUP_ID, GatewayConstant.CONFIG_TIMEOUT);
            updateRoute(routeConfig);

            // 配置中心监听，更新、发布动态路由配置
            configService.addListener(GatewayConstant.DATA_ID, GatewayConstant.GROUP_ID, new AbstractListener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    updateRoute(configInfo);
                }
            });

        } catch (NacosException e) {
            log.error("路由配置更新失败：{}", e.getMessage(), e);
        }
    }

    /**
     * 刷新网关路由配置
     *
     * @param routeConfig 待刷新路由配置
     */
    private void updateRoute(String routeConfig) {
        routeConfig = routeConfig.replaceAll("\\$\\{service_prefix}",service_prefix);
        routeConfig = routeConfig.replaceAll("\\$\\{namespace}",namespace);

        log.info("配置中心路由：{}", routeConfig);
        Yaml yaml = new Yaml();
        GatewayRoute gatewayRoute = yaml.loadAs(routeConfig, GatewayRoute.class);
        gatewayRoute.getRoutes().forEach(route -> {
            log.info("加载网关路由：{},{}", route.getId(), route);
            routeDefinitionWriter.save(Mono.just(route)).subscribe();
        });
        log.info("路由配置更新完成");
    }
}
